import 'dart:async';

import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:sqflite/sqlite_api.dart';
import 'package:ty_smart_watch/bean/receive_data_bean.dart';
import 'package:ty_smart_watch/ble/data_analysis.dart';
import 'package:ty_smart_watch/ble/update_ble_to_view.dart';
import 'package:ty_smart_watch/common/function_id.dart';
import 'package:ty_smart_watch/common/viewmodel.dart';
import 'package:ty_smart_watch/db/device_in_db_controller.dart';
import 'package:ty_smart_watch/entity/connected_device_entity.dart';
import 'package:ty_smart_watch/page/scandevices/controller/scan_device_data.dart';
import 'package:ty_smart_watch/page/watch_setting_page/controller/watch_setting_controller.dart';
import 'package:ty_smart_watch/utils/Log.dart';
import 'package:ty_smart_watch/utils/db_util.dart';

import 'connected_device_controller.dart';

class BleUtil {
  BleUtil._internal();

  factory BleUtil() => _instance;
  static final BleUtil _instance = BleUtil._internal();

  //蓝牙扫描库
  static final flutterReactiveBle = FlutterReactiveBle();

  //扫描数据Controller
  // static final ScanDeviceController controller = Get.find();

  static final ScanDeviceController controller = Get.put(ScanDeviceController());
  static final DeviceInDbController dbController = Get.find();

  static Timer? timer;

  //扫描流
  static var _scan;

  //蓝牙连接的特征
  // static final Map<DiscoveredDevice, StreamSubscription<ConnectionStateUpdate>>
  //     connectDeviceMapWithDevice = {};

  //蓝牙连接的特征
  static final Map<String, StreamSubscription<ConnectionStateUpdate>> connectDeviceMap = {};

  static startScanDevice() async {
    //判断是否有蓝牙扫描权限
    bool hasPermission = await requestBlePermissions();
    if (!hasPermission) {
      print("没有蓝牙权限");
      return;
    }

    //清除扫描到设备的列表
    clearDeviceList();

    //开始扫描
    _scan = flutterReactiveBle
        .scanForDevices(withServices: [], scanMode: ScanMode.lowLatency).listen((device) {
      //返回的device是可以扫描到的设备
      //判断如果设备有名字且连接状态是可连接的,就更新到连接设备列表
      if (device.name.isNotEmpty && device.connectable == Connectable.available) {
        // Log.d("发现设备： ${device}  >>  ${device.manufacturerData.length}");
        if (checkIsTyDevice(device.manufacturerData, device.id)) {
          // 暂停流
          _scan.pause();
          // 更新设备列表
          controller.updateDevice(device);
          // 恢复流
          _scan.resume();
        }
      }
    }, onError: (e) {
      print("onError = $e");
    });

    //启动一个定时器,自动停止设备扫描.
    timer ??= Timer(
      const Duration(milliseconds: 10 * 1000),
      () {
        // 延迟执行的代码,取消扫描
        cancelScan();
      },
    );
  }

  static bool checkIsTyDevice(List<int> manufacturerData, String mac) {
    if (manufacturerData.length != 14) return false;
    List<int> macBytes = manufacturerData.sublist(manufacturerData.length - 6);
    String macAddress =
        macBytes.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join(':').toUpperCase();
    Log.d("raw mac : $mac  >>  $macAddress  >>  ${macAddress == mac}");
    return macAddress == mac;
  }

  ///清空Device搜索列表
  static clearDeviceList() => controller.clearDeviceList();

  ///取消扫描
  static cancelScan() {
    Log.d("取消扫描");
    _scan.cancel();
    timer?.cancel();
    timer = null;
  }

  ///获取蓝牙权限的方法
  static Future<bool> requestBlePermissions() async {
    // You can request multiple permissions at once.
    Map<Permission, PermissionStatus> statuses = await [
      Permission.bluetoothScan,
      Permission.bluetoothConnect,
    ].request();
    print(statuses[Permission.bluetoothScan]);
    print(statuses[Permission.bluetoothConnect]);
    return statuses[Permission.bluetoothScan] == PermissionStatus.granted &&
        statuses[Permission.bluetoothConnect] == PermissionStatus.granted;
  }

  static DeviceController connectedDeviceController = Get.find();

  ///连接设备
  static connectDevice(DiscoveredDevice device, Function() initBleData) {
    //停止扫描
    cancelScan();
    //连接设备
    var _connectionStreamSubscription;

    _connectionStreamSubscription = flutterReactiveBle
        .connectToDevice(
      id: device.id,
      servicesWithCharacteristicsToDiscover: {
        // Uuid.parse("fff0"): [
        //   Uuid.parse("fff1"),
        //   Uuid.parse("fff2"),
        //   Uuid.parse("fff3"),
        //   Uuid.parse("fff4"),
        //   Uuid.parse("fff5")
        // ]
      },
      connectionTimeout: const Duration(seconds: 10),
    )
        .listen((connectionState) async {
      Log.d("设备连接状态 :   ${device.id}  --  ${connectionState.connectionState}");
      if (connectionState.connectionState == DeviceConnectionState.connected) {
        _discoverServices(connectionState.deviceId);
        connectDeviceMap[device.id] = _connectionStreamSubscription;
        connectedDeviceController.updateConnectedDeviceMap(connectDeviceMap);

        readBleData(device.id);
        SmartDialog.dismiss(status: SmartStatus.loading);
        SmartDialog.showToast("${device.name} 连接成功");
        // initBleData();
        // 设备连接成功，发送绑定协议
        BleUtil.writeBleData(device.id, BleUtil.makeWriteData(functionId: BIND));

        await insertDeviceToDb(device.id, device.name);
        Get.back();
      }
      if (connectionState.connectionState == DeviceConnectionState.connecting) {
        SmartDialog.showLoading(
            msg: "${device.name} 连接中", clickMaskDismiss: false, backDismiss: false);
      }
      if (connectionState.connectionState == DeviceConnectionState.disconnected) {
        SmartDialog.showLoading(
            msg: "${device.name} 连接断开", displayTime: const Duration(seconds: 2));
      }
      // Handle connection state updates
    }, onError: (Object error) {
      print("error1 =$error");
      // Handle a possible error
    });
  }

  static connectToDevice(String mId, Map<Uuid, List<Uuid>>? mServicesWithCharacteristicsToDiscover,
      Function() initBleData) {
    //连接设备
    var _connectionStreamSubscription;
    _connectionStreamSubscription = flutterReactiveBle
        .connectToDevice(
      id: mId,
      servicesWithCharacteristicsToDiscover: mServicesWithCharacteristicsToDiscover,
      connectionTimeout: const Duration(seconds: 5),
    )
        .listen((connectionState) {
      // Handle connection state updates
    }, onError: (Object error) {
      // Handle a possible error
    });
  }

  static connectToAdvertisingDevice(String mId, List<Uuid> mWithServices,
      Map<Uuid, List<Uuid>>? mServicesWithCharacteristicsToDiscover, Function() initBleData) {
    //连接设备
    var _connectionStreamSubscription;
    _connectionStreamSubscription = flutterReactiveBle
        .connectToAdvertisingDevice(
      id: mId,
      withServices: mWithServices,
      prescanDuration: const Duration(seconds: 5),
      servicesWithCharacteristicsToDiscover: mServicesWithCharacteristicsToDiscover,
      connectionTimeout: const Duration(seconds: 5),
    )
        .listen((connectionState) async {
      Log.d("设备连接状态 :   $mId  --  ${connectionState.connectionState}");
      if (connectionState.connectionState == DeviceConnectionState.connected) {
        _discoverServices(connectionState.deviceId);
        connectDeviceMap[mId] = _connectionStreamSubscription;
        connectedDeviceController.updateConnectedDeviceMap(connectDeviceMap);

        readBleData(mId);
        SmartDialog.dismiss(status: SmartStatus.loading);
        SmartDialog.showToast("$mId 连接成功");
        initBleData();
        // Get.back();

        // DbUtil dbUtil = DbUtil();
        // Database dataBase = await dbUtil.getDatabase();
        // ConnectedDeviceEntity entity = ConnectedDeviceEntity(address: mId, name: "HH-029");
        // dbUtil.insertData(entity, dataBase);
      }
      if (connectionState.connectionState == DeviceConnectionState.connecting) {
        SmartDialog.showLoading(msg: "$mId 连接中", clickMaskDismiss: false, backDismiss: false);
      }
      if (connectionState.connectionState == DeviceConnectionState.disconnected) {
        SmartDialog.showLoading(msg: "$mId 连接断开", displayTime: const Duration(seconds: 2));
        _connectionStreamSubscription.cancel();
      }

      // Handle connection state updates
    }, onError: (Object error) {
      print("error1 =$error");
      // Handle a possible error
    });
  }

  static _discoverServices(String deviceId) async {
    List<DiscoveredService> serviceList = await flutterReactiveBle.discoverServices(deviceId);
    // Log.d("services=$serviceList");
    for (int i = 0; i < serviceList.length; i++) {
      DiscoveredService discoveredService = serviceList[i];
      Log.d("discoveredService: $discoveredService");
      // if (discoveredService.serviceId == Uuid.parse("fff0")) {
      //   if (discoveredService.characteristicIds.length < 4) {
      //     print("长度不够用");
      //   }
      // }
    }
  }

  ///断开连接设备
  static disconnectDevice(String mac) {
    Log.d("断开连接设备mac : $mac");
    StreamSubscription<ConnectionStateUpdate>? subscription = connectDeviceMap[mac];
    Log.d("开始断连设备");
    if (subscription != null) {
      subscription.cancel();
    }
  }

  ///断开全部连接设备
  static disconnectAllDevice() {
    Log.d("IN -- 断开全部连接设备:$connectDeviceMap");
    for (var stream in connectDeviceMap.values) {
      stream.cancel();
    }
    Log.d("OUT -- 断开全部连接设备:$connectDeviceMap");
  }

  ///读取蓝牙数据
  ///TODO 每多执行一次这个方法， 回调次数将指数级增加，即：点击次数的平方次回调。
  // static readBleData() async {
  //   final characteristic = QualifiedCharacteristic(
  //       // serviceId: Uuid.parse("0000ffe0-e6b7-bbe7-bfbc-e7b2bee5af86"), //hh-029
  //       // characteristicId: Uuid.parse("0000ffe1-e6b7-bbe7-bfbc-e7b2bee5af86"), //hh-029
  //       serviceId: Uuid.parse("fff0"),
  //       characteristicId: Uuid.parse("fff1"),
  //       deviceId: "EC:B1:AC:00:04:4A");
  //   flutterReactiveBle.subscribeToCharacteristic(characteristic).listen((data) {
  //     // code to handle incoming data
  //     print("--上报来的数据data = $data");
  //   }, onError: (dynamic error) {
  //     // code to handle errors
  //   });
  // }

  ///读取蓝牙数据
  ///TODO 每多执行一次这个方法， 回调次数将指数级增加，即：点击次数的平方次回调。
  static readBleDataWithDevice(DiscoveredDevice device) async {
    final characteristic = QualifiedCharacteristic(
        serviceId: Uuid.parse("0000ffe0-e6b7-bbe7-bfbc-e7b2bee5af86"), //hh-029
        characteristicId: Uuid.parse("0000ffe1-e6b7-bbe7-bfbc-e7b2bee5af86"), //hh-029
        // serviceId: Uuid.parse("fff0"),
        // characteristicId: Uuid.parse("fff1"),
        deviceId: device.id);
    flutterReactiveBle.subscribeToCharacteristic(characteristic).listen((data) {
      // code to handle incoming data
      print("  ${device.id}   --  上报来的数据data = $data");
      ReceiveDataBean dataBean = DataAnalysis.instance!.analysisReceiveData(data);
      print("  ${device.id}   --  上报来的数据dataBean = ${dataBean.toString()}");
      UpdateBleToView.instance!.updateToView(dataBean);
    }, onError: (dynamic error) {
      // code to handle errors
    });
  }

  ///读取蓝牙数据
  ///TODO 每多执行一次这个方法， 回调次数将指数级增加，即：点击次数的平方次回调。
  static readBleData(String id) async {
    final characteristic = QualifiedCharacteristic(
        serviceId: Uuid.parse("0000ffe0-e6b7-bbe7-bfbc-e7b2bee5af86"), //hh-029
        characteristicId: Uuid.parse("0000ffe1-e6b7-bbe7-bfbc-e7b2bee5af86"), //hh-029
        // serviceId: Uuid.parse("fff0"),
        // characteristicId: Uuid.parse("fff1"),
        deviceId: id);
    flutterReactiveBle.subscribeToCharacteristic(characteristic).listen((data) {
      // code to handle incoming data
      Log.d("  $id   --  上报来的数据data = $data");
      ReceiveDataBean dataBean = DataAnalysis.instance!.analysisReceiveData(data);
      Log.d("  $id   --  上报来的数据dataBean = ${dataBean.toString()}");

      if (dataBean.functionId == BIND) {
        int res = dataBean.dataLongMap["bind"] ?? 0;
        if (res == 0) {
          //设备绑定成功
          ViewModel.getInitInfo(id);
        }
        if (res == 1) {
          //设备绑定失败，断开当前设备。
          disconnectDevice(id);
          return;
        }
      }

      try {
        WatchSettingController watchSettingController = Get.find();
        watchSettingController.updateDataBean(dataBean);
      } catch (e) {
        Log.d("$e");
      }

      UpdateBleToView.instance!.updateToView(dataBean);
    }, onError: (dynamic error) {
      // code to handle errors
    });
  }

  ///写蓝牙数据
  // static writeBleData() async {
  //   final writeCharacteristic = QualifiedCharacteristic(
  //       serviceId: Uuid.parse("0000ffe0-e6b7-bbe7-bfbc-e7b2bee5af86"), //hh-029
  //       characteristicId: Uuid.parse("0000ffe2-e6b7-bbe7-bfbc-e7b2bee5af86"), //hh-029
  //       // serviceId: Uuid.parse("0000fff0-0000-1000-8000-00805f9b34fb"),
  //       // characteristicId: Uuid.parse("0000fff2-0000-1000-8000-00805f9b34fb"),
  //       deviceId: "36:ED:EC:E5:E4:A3");
  //   final intList = [0x54, 0x59, 0x01, 0x01, 0x00, 0x00, 0x03, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00];
  //   await flutterReactiveBle.writeCharacteristicWithoutResponse(writeCharacteristic,
  //       value: intList);
  // }

  ///写蓝牙数据
  static writeBleData(String id, List<int> data) async {
    final writeCharacteristic = QualifiedCharacteristic(
        serviceId: Uuid.parse("0000ffe0-e6b7-bbe7-bfbc-e7b2bee5af86"), //hh-029
        characteristicId: Uuid.parse("0000ffe2-e6b7-bbe7-bfbc-e7b2bee5af86"), //hh-029
        // serviceId: Uuid.parse("0000fff0-0000-1000-8000-00805f9b34fb"),
        // characteristicId: Uuid.parse("0000fff2-0000-1000-8000-00805f9b34fb"),
        deviceId: id);
    // final intList = [0x54, 0x59, 0x01, 0x01, 0x00, 0x00, 0x03, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00];
    await flutterReactiveBle.writeCharacteristicWithoutResponse(writeCharacteristic, value: data);
  }

  ///读取设备的信息(不清楚具体用法)
  static readBleDeviceData() async {
    final characteristic = QualifiedCharacteristic(
        serviceId: Uuid.parse("0000ffe0-e6b7-bbe7-bfbc-e7b2bee5af86"), //hh-029
        characteristicId: Uuid.parse("0000ffe1-e6b7-bbe7-bfbc-e7b2bee5af86"), //hh-029
        // serviceId: Uuid.parse("0000fff0-0000-1000-8000-00805f9b34fb"),
        // characteristicId: Uuid.parse("0000fff2-0000-1000-8000-00805f9b34fb"),
        deviceId: "36:ED:EC:E5:E4:A3");
    final response = await flutterReactiveBle.readCharacteristic(characteristic);
    Log.d("response= \n $response");
  }

  ///将连接的设备插入到数据库中
  static Future<void> insertDeviceToDb(String id, String name) async {
    DbUtil dbUtil = DbUtil();
    var allDeviceList = await dbUtil.getAllDevice();
    bool hasDeviceInDb = allDeviceList.any((dbDevice) => dbDevice["address"] == id);
    Log.d("数据库中是否包含$name : $hasDeviceInDb");
    //如果数据库中不包含该设备，则存入数据库
    if (!hasDeviceInDb) {
      Database dataBase = await dbUtil.getDatabase();
      ConnectedDeviceEntity entity = ConnectedDeviceEntity(
          address: id, name: name, lastConnectTimeStamp: DateTime.now().millisecondsSinceEpoch);
      dbUtil.insertData(entity, dataBase);
      //更新数据库的Controller
      var newList = await dbUtil.getAllDevice();
      dbController.updateDbList(newList);
    }
  }

  /// 创建常规写入数据
  /// [currFrame] 当前帧
  /// [totalFrame] 总帧数
  /// [functionId] 功能码
  /// [data] 数据
  static List<int> makeWriteData({
    int currFrame = 1,
    int totalFrame = 1,
    required int functionId,
    List<int> data = const [],
  }) {
    int length = data.length;
    int checkSum =
        (functionId >> 8) & 0xFF + functionId & 0xFF + (length >> 8) & 0xFF + length & 0xFF;

    for (int d in data) {
      checkSum += d & 0xFF;
    }

    int packageLength = 2 + 2 + length;

    List<int> writeData = [
      0x54,
      0x59,
      currFrame & 0xFF,
      totalFrame & 0xFF,
      0x00,
//    0x80,
      (checkSum >> 8) & 0xFF,
      checkSum & 0xFF,
      (packageLength >> 8) & 0xFF,
      packageLength & 0xFF,
      (functionId >> 8) & 0xFF,
      functionId & 0xFF,
      (length >> 8) & 0xFF,
      length & 0xFF,
    ];

    writeData.addAll(data);

    return writeData;
  }
}
